package com.gitee.l0km.beanfilter.core;

import static com.google.common.base.Preconditions.checkNotNull;

import com.google.common.base.Predicate;
import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;

/**
 * 基于{@link Supplier}提供过滤实例的字段和值过滤器实现
 * @author guyadong
 */
public class SupplyFilter implements IValueFilter,IFieldFilter{
	public static final SupplyFilter DEFAULT_INSTANCE = new SupplyFilter();
	protected final Supplier<IFilter> fieldFilterSupplier;
	protected final Supplier<IFilter> valueFilterSupplier;
	private SupplyFilter() {
		this(Suppliers.ofInstance(IFieldFilter.DEFAULT_INSTANCE) ,Suppliers.ofInstance(IValueFilter.DEFAULT_INSTANCE));
	}
	SupplyFilter(Supplier<? extends IFilter> supplier) {
		this(supplier, supplier);
	}
	@SuppressWarnings("unchecked")
	SupplyFilter(Supplier<? extends IFilter> fieldFilterSupplier, Supplier<? extends IFilter> valueFilterSupplier) {
		this.fieldFilterSupplier = (Supplier<IFilter>) checkNotNull(fieldFilterSupplier,"fieldFilterSupplier is null");
		this.valueFilterSupplier = (Supplier<IFilter>) checkNotNull(valueFilterSupplier,"valueFilterSupplier is null");
	}
	@Override
	public Object process(Class<?> clazz, String name, Object value) {
		return getValueFilterOrDefault().process(clazz, name, value);
	}
	@Override
	public boolean permit(Class<?> clazz, String fieldName) {
		return getFieldFilterOrDefault().permit(clazz, fieldName);
	}
	/**
	 * 从 {@link #fieldFilterSupplier} 返回 {@link IFieldFilter}实例<br>
	 * 如果从 {@link #fieldFilterSupplier} 返回的 {@link IFieldFilter}实例为默认实现
	 * 或为容器( {@link ICombinedFilter} )且为空则返回{@code null}
	 * @see #getFilter(IFilter, Class, Class)
	 */
	public IFieldFilter getFieldFilter() {
		IFilter filter = fieldFilterSupplier.get();
		return getFilter(filter, IFieldFilter.class,IFieldFilter.DefaultFieldFilter.class);
	}
	/**
	 * 从 {@link #valueFilterSupplier} 返回 {@link IValueFilter}实例<br>
	 * 如果从 {@link #valueFilterSupplier} 返回的 {@link IValueFilter}实例为默认实现
	 * 或为容器( {@link ICombinedFilter} )且为空则返回{@code null}
	 * @see #getFilter(IFilter, Class, Class)
	 */	
	public IValueFilter getValueFilter() {
		IFilter filter =  valueFilterSupplier.get();
		return getFilter(filter, IValueFilter.class,IValueFilter.DefaultValueFilter.class);
	}
	/**
	 * 检查{@code filter}类型，
	 * 如果是默认实现{@code defaultImpl}或是{@link ICombinedFilter}实例，且不包含目标类型的过滤器实例则返回{@code null}
	 * @param <F>
	 * @param filter 过滤器
	 * @param targetType 目标过滤器类型
	 * @param defaultImpl 目标过滤器类型的默认实例类型
	 */
	private static <F extends IFilter> F getFilter(IFilter filter,Class<F>targetType,Class<? extends F> defaultImpl) {
		if(targetType.isInstance(filter)) {
			if(!(defaultImpl.isInstance(filter))) {
				if(!(filter instanceof ICombinedFilter) || !((ICombinedFilter)filter).isEmpty(targetType)) {
					return targetType.cast(filter);
				}
			}
		}
		return null;
	}
	/**
	 * 从 {@link #fieldFilterSupplier} 返回 {@link IFieldFilter}实例<br>
	 * 如果不是{@link IFieldFilter}实例返回默认实例 {@link IFieldFilter#DEFAULT_INSTANCE}
	 */
	public IFieldFilter getFieldFilterOrDefault() {
		IFilter filter = fieldFilterSupplier.get();
		return filter instanceof IFieldFilter 
				? (IFieldFilter)filter
				: IFieldFilter.DEFAULT_INSTANCE; 
	}
	/**
	 * 从 {@link #valueFilterSupplier} 返回 {@link IValueFilter}实例<br>
	 * 如果不是{@link IValueFilter}实例返回默认实例 {@link IValueFilter#DEFAULT_INSTANCE}
	 */
	public IValueFilter getValueFilterOrDefault() {
		IFilter filter =  valueFilterSupplier.get();
		return (filter instanceof IValueFilter)
				? (IValueFilter)filter
				: IValueFilter.DEFAULT_INSTANCE;
	}
	public Predicate<String> asFieldNamePredicate(final Class<?> clazz,final boolean negate){
		return new Predicate<String>() {
			@Override
			public boolean apply(String input) {
				return negate ?  (!permit(clazz,input)) :  permit(clazz,input);
			}};
	}
	public Predicate<String> asFieldNameNotPredicate(final Class<?> clazz){
		return new Predicate<String>() {
			@Override
			public boolean apply(String input) {
				return !permit(clazz,input);
			}};
	}
	public static  SupplyFilter of(Supplier<? extends IFilter> supplier) {
		return new SupplyFilter(supplier);
	}
	public static SupplyFilter of(IFilter filter) {
		if(filter instanceof SupplyFilter) {
			return (SupplyFilter) filter;
		}
		return of(Suppliers.ofInstance(filter));
	}
	public static  SupplyFilter combine(Supplier<IFieldFilter> fieldFilterSupplier,Supplier<IValueFilter> valueFilterSupplier) {
		return new SupplyFilter(fieldFilterSupplier,valueFilterSupplier);
	}
	public static SupplyFilter combine(IFieldFilter fieldFilter,IValueFilter valueFilter) {
		if(fieldFilter instanceof SupplyFilter) {
			return (SupplyFilter) fieldFilter;
		}
		if(valueFilter instanceof SupplyFilter) {
			return (SupplyFilter) valueFilter;
		}
		return combine(Suppliers.ofInstance(fieldFilter),Suppliers.ofInstance(valueFilter));
	}
	public static  SupplyFilter combine2(Supplier<? extends IFilter> fieldFilterSupplier,Supplier<? extends IFilter> valueFilterSupplier) {
		if(null == fieldFilterSupplier) {
			fieldFilterSupplier = valueFilterSupplier;
		}
		if(null == valueFilterSupplier) {
			valueFilterSupplier = fieldFilterSupplier;
		}
		if(fieldFilterSupplier == valueFilterSupplier) {
			return of(fieldFilterSupplier);
		}
		return new SupplyFilter(fieldFilterSupplier,valueFilterSupplier);
	}
}